package com.lry.util;

import com.lry.util.geo.GeoUtil;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.UrlResource;

/**
 * 行政区划解析工具
 *
 * @author ALI
 * @since 2023/5/10
 */
@Slf4j
public class AreaUtil {

    private static final String[] ZU = new String[] {"省", "市", "县", "区", "西区", "东区", "北区", "南区", "州",
        "自治", "经济开发", "工业园", "朝鲜族", "苗族", "藏族",
        "彝族", "羌族", "侗族", "布衣族", "回族", "白族", "傈傈族", "傣族", "景颇族", "（", "）", "(", ")"};
    // key:code_name, value:json
    private static final Map<String, String> JSON_CACHE = new HashMap<>();
    // key:code，value:single name
    private static final Map<String, String> SINGLE_NAME_CACHE = new HashMap<>();
    // key: 区县名称， value:areaCode
    private static final Map<String, String> SINGLE_CODE_CACHE = new HashMap<>();
    // key:code, value:province city name
    private static final Map<String, String> PCN_NAME_CACHE = new HashMap<>();
    // key:province city name, value:code
    private static final Map<String, String> PCN_CODE_CACHE = new HashMap<>();
    // key:简化name， value:code
    private static final Map<String, String> SIMPLE_CODE_CACHE = new HashMap<>();
    private static final Map<String, String> SIMPLE_CODE_CACHE2 = new HashMap<>();
    private static final String EXT_FILE_PATH = System.getProperty("user.dir") + File.separator + "ext_areaCode.txt";
    private static final Map<String, Integer> MAX_CODE = new HashMap<>();
    private static int MAX_AREA_CODE = 510000;

    static {
        initJson();
        initCode();
        initExt();
    }

    /**
     * 用来做areaCode生成
     *
     * @param city    市级
     * @param name    县级
     * @param address 详细地址
     * @return 生成的areaCode
     */
    public static String writeAreaCode(String city, String name, String address) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(EXT_FILE_PATH, true))) {
            if (StringUtils.isBlank(address)) {
                address = city + name;
            }
            String code = getmax(address);
            if (code != null && !code.equals("--")) {
                code = String.valueOf(Integer.parseInt(code) + 1);
            }
            String simpleAddress = address.replaceAll(String.join("|", ZU), "");
            writer.write(String.format("%s %s %s %s\r\n", code, address, simpleAddress, address));
            writer.flush();
            PCN_NAME_CACHE.put(code, address);
            PCN_CODE_CACHE.put(address, code);
            SIMPLE_CODE_CACHE.put(address, code);
            SIMPLE_CODE_CACHE2.put(simpleAddress, code);
            SINGLE_NAME_CACHE.put(code, name);
            SINGLE_CODE_CACHE.put(name, code);
            return code;
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 根据地址获取行政区划编码
     *
     * @param address 地址
     * @return 行政区划编码
     */
    public static String getCode(String address) {
        if (StringUtils.isBlank(address)) {
            return null;
        }
        String code = PCN_CODE_CACHE.get(address);
        if (StringUtils.isNotBlank(code)) {
            return code;
        }
        code = SINGLE_CODE_CACHE.get(address);
        if (code != null) {
            return code;
        }
        // 全称地址
        code = PCN_CODE_CACHE.get(address);
        if (code == null) {
            // 简化地址
            code = SIMPLE_CODE_CACHE.get(address);
        }
        if (StringUtils.isNotBlank(code)) {
            return code;
        }
        // 不完整地址，不规范地址
        code = getCodeFromAreaFeature(address, "县");
        if (code == null) {
            code = getCodeFromAreaFeature(address, "区");
        }
        if (code == null) {
            code = getCodeFromAreaFeature(address, "州");
        }
        // 有些市级下的区域的名称也包含市
        if (code == null || code.endsWith("00")) {
            code = getCodeFromAreaFeature(address, "市");
        }
        if (code == null) {
            code = getCodeFromAreaFeature(address, "省");
        }
        return code;
    }

    public static void main(String[] args) {
        String name = "宜宾市三江新区";
        //        String name = "达州市万源市";
        String code = getCode(name);
        System.out.println(code);
        System.out.println(getName(code));
        //        String s = writeAreaCode("宜宾市", "三江新区2", null);
        //        System.out.println(s);
    }

    /**
     * 更加行政区划编码获取地名
     *
     * @param code 行政区划编码
     */
    public static String getName(String code) {
        return SINGLE_NAME_CACHE.get(code);
    }

    /**
     * 更加经纬度获取行政区划编码
     * 准确率低
     *
     * @param lng 经度
     * @param lat 纬度
     */
    public static String getAreaCode(Double lng, Double lat) {
        if (lng == null || lat == null || lng == 0 || lat == 0) {
            return null;
        }
        for (Map.Entry<String, String> entry : JSON_CACHE.entrySet()) {
            try {
                if (GeoUtil.inArea(lng, lat, GeoUtil.geoCoordinateToJSONArray(entry.getValue()))) {
                    String[] s = entry.getKey().split("_");
                    return s[0];
                }
            } catch (Exception e) {
                System.out.println("不合规的坐标集合" + e.getMessage() + " -- " + entry.getKey());
            }
        }
        return null;
    }

    private static String getmax(String city) {
        Integer integer = MAX_CODE.get(city);
        String code = "--";
        if (integer == null) {
            code = getCode(city);
            if (code != null) {
                code = code.substring(0, 4) + 90;
            } else {
                code = "--";
            }
        } else {
            code = String.valueOf(integer);
        }
        return code;
    }

    private static String getCodeFromAreaFeature(String name, String feature, String... removeFeature) {
        String dealName = name;
        // 取下级
        if (StringUtils.isNotBlank(feature)) {
            dealName = name.substring(name.indexOf(feature) + 1).trim();
        }
        if (StringUtils.isNotBlank(dealName)) {
            for (Map.Entry<String, String> tempEntry : SINGLE_NAME_CACHE.entrySet()) {
                if (tempEntry.getValue().contains(dealName)) {
                    return tempEntry.getKey();
                }
            }
        }
        String result = null;
        // 取当前级
        // 还是没有，应该不是区域名称，返回市级
        String simpleName = name.substring(0, name.indexOf(feature) + 1);
        if (StringUtils.isBlank(simpleName)) {
            return null;
        }
        for (Map.Entry<String, String> tempEntry : SINGLE_NAME_CACHE.entrySet()) {
            if (tempEntry.getValue().contains(simpleName)) {
                return tempEntry.getKey();
            }
        }
        // 全称
        for (Map.Entry<String, String> entry : PCN_CODE_CACHE.entrySet()) {
            //            String[] split = simpleName.split("省|市|自治州");
            //            List<String> collect = Arrays.stream(split).filter(StringUtils::isNotBlank).collect
            //            (Collectors.toList());
            //            if (entry.getKey().endsWith(collect.get(collect.size() - 1))) {
            if (entry.getKey().endsWith(simpleName)) {
                result = entry.getValue();
            }
        }
        // 简称
        if (result == null) {
            simpleName = simpleName.replaceAll(String.join("|", ZU), "");
            //            String result2 = SIMPLE_CODE_CACHE.get(simpleName);
            for (Map.Entry<String, String> entry : SIMPLE_CODE_CACHE.entrySet()) {
                if (entry.getKey().endsWith(simpleName)) {
                    result = entry.getValue();
                }
            }
            if (result == null) {
                for (Map.Entry<String, String> entry : SIMPLE_CODE_CACHE2.entrySet()) {
                    if (entry.getKey().endsWith(simpleName)) {
                        result = entry.getValue();
                    }
                }
                //                result = SIMPLE_CODE_CACHE2.get(simpleName);
            }
            //            if (result2 != null) {
            //                result = result2;
            //            }
        }
        if (result == null || result.endsWith("00")) {
            // todo 省 -》县 跳过市  还不够精确
            boolean has = false;
            int sub = simpleName.length() >= 4 ? simpleName.length() - 4 : simpleName.length() - 2;
            for (Map.Entry<String, String> entry : SIMPLE_CODE_CACHE2.entrySet()) {
                String temp = simpleName.substring(sub);
                if (temp.length() > 2 && entry.getKey().endsWith(temp)) {
                    result = entry.getValue();
                    has = true;
                }
            }
            for (Map.Entry<String, String> entry : SIMPLE_CODE_CACHE2.entrySet()) {
                String temp = simpleName.substring(sub + 2);
                if (temp.length() > 2 && entry.getKey().endsWith(temp)) {
                    result = entry.getValue();
                }
            }

        }

        return result;
    }

    static void initJson() {
        try {
            URL url = AreaUtil.class.getClassLoader().getResource("areaJson.txt");
            UrlResource resource = new UrlResource(url);
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
                String s = null;
                while ((s = reader.readLine()) != null) {
                    String[] split = s.split("\\s");
                    JSON_CACHE.put(split[0] + "_" + split[1], split[2]);
                    SINGLE_NAME_CACHE.put(split[0], split[1]);
                    SINGLE_CODE_CACHE.put(split[1], split[0]);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("初始化缓存失败！" + e);
        }
    }

    static void initExt() {
        File file = new File(EXT_FILE_PATH);
        if (!file.exists()) {
            return;
        }
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String s = null;
            while ((s = reader.readLine()) != null) {
                String[] split = s.split("\\s");
                if (split[0].endsWith("--")) {
                    continue;
                }
                PCN_NAME_CACHE.put(split[0], split[1]);
                PCN_CODE_CACHE.put(split[1], split[0]);
                SINGLE_NAME_CACHE.put(split[0], split[1]);
                if (StringUtils.isNotBlank(split[2])) {
                    SIMPLE_CODE_CACHE.put(split[2], split[0]);
                    SIMPLE_CODE_CACHE2.put(split[2].replaceAll(String.join("|", ZU), ""), split[0]);
                }
                String code = getmax(split[1]);
                if (code != null && !code.equals("--") && Integer.parseInt(split[0]) > Integer.parseInt(code)) {
                    MAX_CODE.put(split[1], Integer.parseInt(split[0]));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化EXT缓存失败！" + e);
        }
    }

    static void initCode() {
        try {
            URL url = AreaUtil.class.getClassLoader().getResource("areaCode.txt");
            UrlResource resource = new UrlResource(url);
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
                String s = null;
                while ((s = reader.readLine()) != null) {
                    String[] split = s.split("\\s");
                    PCN_NAME_CACHE.put(split[0], split[1]);
                    PCN_CODE_CACHE.put(split[1], split[0]);
                    SIMPLE_CODE_CACHE.put(split[2], split[0]);
                    SIMPLE_CODE_CACHE2.put(split[2].replaceAll(String.join("|", ZU), ""), split[0]);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("初始化缓存失败！" + e);
        }
    }
}
